using System;
using System.Collections;
using System.Data;
using Sedna.Core.Controller;
using Spring.Context.Support;

namespace Sedna.Core.Persistence
{
	/// <summary>
	/// abstract class that serves as a basis for any subsidiary filter implementations
	/// this class provides basic logic and contaners for such common filter functionality 
	/// as starting record index (zero based), amount of recorrds per page and sorting.
	/// Apart from that this class provides the basic implementation of the Reset() method
	/// to reset the aformentioned common filter properties. Therefore, all child subclasses have
	/// to call this base.Reset() method so as to be sure that all common properties are
	/// reset properly
	/// </summary>
	[Serializable]
	public abstract class AbstractFilterState : IFilterState
	{
        private static IHqlExecutor defaultExecutor;
	    
		private int startIndex = 0;
		private int amount = -1;
		private bool isAsc;
		private string sortExpression;
        private int totalAmount = -1;
	    
	    static AbstractFilterState()
	    {
	    }
	    
	    /// <remarks>
        /// We encourage problems with context initialization if we lookup defaultExecutor in advance.
        /// Since some FilterStates may be placed in Spring context itself, a call like 
        /// <code>SpringContextFactory.GetContext().GetObject("infra.HqlExecutor")</code> may 
        /// cause cyclic call since SpringContextFactory is not inited at the moment.
	    /// </remarks>
	    protected static IHqlExecutor DefaultExecutor
	    {
	        get
	        {
	            if (defaultExecutor==null)
	            {
                    defaultExecutor = (IHqlExecutor)SpringContextFactory.GetContext().GetObject("infra.HqlExecutor");
                }
                return defaultExecutor;
	        }
	    }

		public virtual int StartIndex
		{
			get { return startIndex; }
			set { startIndex = value; }
		}

		public virtual int Amount
		{
			get { return amount; }
			set { amount = value; }
		}

		public virtual bool IsAsc
		{
			get { return isAsc; }
			set { isAsc = value; }
		}

		public virtual string SortExpression
		{
			get { return sortExpression; }
			set { sortExpression = value; }
		}

        public virtual ICollection LoadData()
        {
            IQueryResult result = DefaultExecutor.Execute(this);
            totalAmount = (result.IsTotalCountDefined ? result.TotalCount : -1);
            return result.Data;
        }
	    
	    public virtual int TotalAmount
	    {
	        get { return totalAmount > 0 ? totalAmount : int.Parse(defaultExecutor.GetTotalAmount(this).ToString());}
	    }
	    
		public virtual IFilterState Reset()
		{
			this.startIndex = 0;
			this.amount = 50;
			this.isAsc = true;
			this.sortExpression = null;

			return this;
		}

		public virtual Object Clone()
		{
			/* Create shallow copy */
			return MemberwiseClone();			
		}

        protected String ParseSortDirection(bool isAsc)
        {
            return isAsc ? "ASC" : "DESC";
        }
	}
}
